module Language.Java.Parser.AST where

import Language.Java.Parser.Lexer

data SourceSpan = SrcSpan { srcFrom :: AlexPosn, srcTo :: AlexPosn } deriving (Show, Eq)

data Program 
    = Programm { progSrcSpan :: SourceSpan, package :: PackageDecl, imports :: ImportDeclList, pClassDeclList :: ClassDeclList }
   deriving (Show, Eq)

data ClassDeclList
    = ClassDeclList { classListSrcSpan :: SourceSpan, classDecl :: ClassDecl, classDeclList :: ClassDeclList }
    | CEmpty
  deriving (Show, Eq)

data ClassDecl 
      = ClassDecl { classSrcSpan :: SourceSpan, classModifiers :: Modifiers, className :: Ident, classExt :: Ident, classMemberList :: ClassMemberList }
      | ClassEnum { classSrcSpan :: SourceSpan, classModifiers :: Modifiers, className :: Ident, enums :: ExpList }
  deriving (Show, Eq)

data ClassMemberDecl
    = ClassMemberMethod     { classMemberSrcSpan :: SourceSpan, methodDecl :: MethodDecl }
    | ClassConstructor      { classMemberSrcSpan :: SourceSpan, constructor :: ConstructorDecl }
    | ClassMemberStatement  { classMemberSrcSpan :: SourceSpan, stmDecl :: Statement }
    | ClassMemberVar        { classMemberSrcSpan :: SourceSpan, varDecl :: VarDecl }
  deriving (Show, Eq)

data ClassMemberList
    = ClassMemberList { classMemberListSrcSpan :: SourceSpan, firstMember :: ClassMemberDecl, memberRest :: ClassMemberList }
    | CMEmpty
  deriving (Show, Eq)

data ConstructorDecl
    = ConstructorDecl {constrScrSpan :: SourceSpan, constrName :: Ident, constrParam :: FormalList, constrStmList :: StatementList }
   deriving (Show, Eq)

data MethodDecl
    = MethodDecl { methodSrcSpan :: SourceSpan, methodType :: Type,  methodName :: Ident, paramList :: FormalList, methodStmList :: StatementList }
    deriving (Show, Eq)

data FormalList = 
    FormalList { fListSrcSpan :: SourceSpan, itemType :: Type, itemName :: Ident, formalList :: FormalList }
    | FEmpty
  deriving (Show, Eq)

data Type =
    TypeArray { typeSrcSpan :: SourceSpan, arrayType :: Type }
    | TypeBoolean { typeSrcSpan :: SourceSpan }
    | TypeInt { typeSrcSpan :: SourceSpan }
    | TypeVoid { typeSrcSpan :: SourceSpan }
    | TypeByte { typeSrcSpan :: SourceSpan }
    | TypeShort { typeSrcSpan :: SourceSpan }
    | TypeLong { typeSrcSpan :: SourceSpan }
    | TypeFloat { typeSrcSpan :: SourceSpan }
    | TypeDouble { typeSrcSpan :: SourceSpan }
    | TypeChar { typeSrcSpan :: SourceSpan }
    | TypeReference { typeSrcSpan :: SourceSpan, typeName :: Ident }
    deriving (Show, Eq)

data Statement
    = Statement String
    | SList { stmSrcSpan :: SourceSpan, sList :: StatementList }
    | SIfElse { stmSrcSpan :: SourceSpan, condExp :: Exp,  ifBody :: Statement, elseBody :: Statement }
    | SIf { stmSrcSpan :: SourceSpan, condExp :: Exp,  ifBody :: Statement }
    | SWhile { stmSrcSpan :: SourceSpan, condExp :: Exp, whileBody :: Statement }
    | SFor { stmSrcSpan :: SourceSpan, forParam :: ForParam, forBody :: Statement }
    | SMethodCall {stmSrcSpan :: SourceSpan, calledMethod :: String, usedArgs :: ExpList }
    | SPrint { stmSrcSpan :: SourceSpan, printExp :: Exp }
    | SEqual { stmSrcSpan :: SourceSpan, sVarName :: Ident, equalExp :: Exp }
    | SArrayEqual {stmSrcSpan :: SourceSpan, arrayName :: Ident, arrayExp :: Exp, equalExp :: Exp }
    | SVarDecl { stmSrcSpan :: SourceSpan, var :: VarDecl }
    | SExp { stmSrcSpan :: SourceSpan, stmExpr :: Exp }
    | SReturn { stmSrcSpan :: SourceSpan, returnExp :: Exp }
    | SAssignment { stmSrcSpan :: SourceSpan, leftHand :: Exp, assSymb :: String, rightHand :: Exp }
--    | SSwitch { stmSrcSpan :: SourceSpan, switchExp :: Exp, cases :: CaseStatements }
    | SBreak { stmSrcSpan :: SourceSpan, breakLable :: Ident }
    | SContinue { stmSrcSpan :: SourceSpan, contLable :: Ident }
    | SLable { stmSrcSpan :: SourceSpan, lable :: Ident }
    | StatementError
    deriving (Show, Eq)

data StatementList
    = StatementList { stmListSrcSpan :: SourceSpan, stmList :: StatementList, stm :: Statement }
    | Empty
    deriving (Show, Eq)


data Exp
    = Exp String
    | ExpOp { expSrcSpan :: SourceSpan, leftExp :: Exp, opSymbol :: String, rightExp :: Exp }
    | ExpComOp { expSrcSpan :: SourceSpan, leftExp :: Exp, opSymbol :: String, rightExp :: Exp }
    | ExpArray { expSrcSpan :: SourceSpan, outerExp :: Exp, innerExp :: Exp } -- "Exp [ Exp ]"
    | ExpFCall { expSrcSpan :: SourceSpan, exp :: Exp, expList :: ExpList } -- Exp ( ExpList )
    | ExpInt { expSrcSpan :: SourceSpan, intValue :: Int }
    | ExpNewType { expSrcSpan :: SourceSpan, exp :: Exp }
    | ExpBool { expSrcSpan :: SourceSpan, boolValue :: Bool } -- True or False
    | ExpIdent { expSrcSpan :: SourceSpan, value :: Ident }
    | ExpQualifiedIdent {expSrcSpan :: SourceSpan, value :: Ident }
    | ExpString { expSrcSpan :: SourceSpan, value :: Ident }
    | ExpChar { expSrcSpan :: SourceSpan, value :: Ident }
    | ExpNewIdent { expSrcSpan :: SourceSpan, name :: Ident } -- new Ident ()
    | ExpParentheses { expSrcSpan :: SourceSpan, exp :: Exp }-- Exp ( Exp )
    | ExpBraces { expSrcSpan :: SourceSpan, expList :: ExpList }
    | ExpThis { expSrcSpan :: SourceSpan }
    | ExpNot { expSrcSpan :: SourceSpan, exp :: Exp }
    | ExpDotExp { expSrcSpan :: SourceSpan, leftExp :: Exp, rightExp :: Exp }
    | ExpInc { expSrcSpan :: SourceSpan, exp :: Exp }
    | ExpDec { expSrcSpan :: SourceSpan, exp :: Exp }
    | ExpVar { expSrcSpan :: SourceSpan, expVar :: VarDecl }
    | ExpShortIf { expSrcSpan :: SourceSpan, leftExp :: Exp, innerExp :: Exp, rightExp :: Exp }
    | ExpSigned { expSrcSpan :: SourceSpan, sign :: String, exp :: Exp }
    | ExpError
    deriving (Show, Eq)

data Ident = IdentLit String deriving (Show, Eq)

data Integer_Literal = IntLit Int deriving (Show, Eq)

data ExpList
    = ExpList { expListSrcSpan :: SourceSpan, exprList :: ExpList, expRest :: ExpRest }
    | ExpListExp { expListSrcSpan :: SourceSpan, expr :: Exp }
    | ExpListEmpty
    deriving (Show, Eq)

data ExpRest
    = ExpRest { expRestSrcSpan :: SourceSpan, restExp :: Exp }
    deriving (Show, Eq)

data QualifiedIdent
    = QualifiedIdent { qIdentSrcSpan :: SourceSpan, idents :: QualifiedIdent, lastIdent :: Ident }
    | QualifiedIdentSingle {qIdentSrcSpan :: SourceSpan, lastIdent :: Ident }
    deriving (Show, Eq)

data ImportDecl
    = ImportDecl {importSrcSpan :: SourceSpan, importedPackage :: String }
    deriving (Show, Eq)

data ImportDeclList
    = ImportDeclList {importListScrSpan :: SourceSpan, importDecl :: ImportDecl, importDeclList :: ImportDeclList }
    | ImportEmpty
    deriving (Show, Eq)

data PackageDecl
    = PackageDecl {packageSrcSpan :: SourceSpan, packageName :: Ident }
    | NoPackage
    deriving (Show, Eq)

data Modifier
    = ModifierFinal { modifierSrcSpan :: SourceSpan }
    | ModifierStatic { modifierSrcSpan :: SourceSpan }
    | ModifierPublic { modifierSrcSpan :: SourceSpan }
    | ModifierPrivate { modifierSrcSpan :: SourceSpan }
    | ModifierAbstract { modifierSrcSpan :: SourceSpan }
    | ModifierProtected { modifierSrcSpan :: SourceSpan }
    deriving (Show, Eq)

data Modifiers
    = Modifiers { modifiersSrcSpan :: SourceSpan, firstMod :: Modifier, restMod :: Modifiers }
    | ModifierEmpty
    deriving (Show, Eq)

data VarDecl
        = VarDecl { varDeclSrcSpan :: SourceSpan, varType :: Type, varName :: Ident }
        | VarDeclAss { varDeclSrcSpan :: SourceSpan, varType :: Type, varName :: Ident, varAss :: Exp }
        deriving (Show, Eq)

data ForParam
        = ForEach  { forParamSrcSpan :: SourceSpan, itType :: Type, itName :: Ident, forSet :: Exp }
        | ForRange { forParamSrcSpan :: SourceSpan, forIt :: Exp, forRange :: Exp, forStep :: Exp }
        deriving (Show, Eq)

{-

data CaseStatements
    = CaseStatementSingle {caseStmsSrcSpan :: SourceSpan, lastCase :: CaseStatement }
    | CaseStatementList   {caseStmsSrcSpan :: SourceSpan, caseList :: CaseStatements, lastCase :: CaseStatement }
    deriving (Show, Eq)

data CaseStatement
    = CaseStm { caseSrcSpan :: SourceSpan, caseLable :: String, caseBlock :: Statement }
    deriving (Show, Eq)
-}    
